package com.grandtech.insurance.common.utils;

import org.apache.commons.lang.StringUtils;

import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class FormatVerify {
  private static final String ERROR_FORMAT="参数格式错误";
  /**
   * 验证纯数字字符串是不是符合指定长度
   *
   * @param str
   * @param length
   * @throws Exception
   */
  public static void StingNumberLength(String str, int length) throws Exception {
    stingIsNumber(str);
    if (str.length() != length) {
      throw new Exception(ERROR_FORMAT);
    }

  }

  /**
   * 验证字符串是不是纯数字
   *
   * @param str
   * @throws Exception
   */
  public static void stingIsNumber(String str) throws Exception {
    EmptyUtil.emptyVerifi(str);
    String format="[0-9]*";
    Pattern pattern = Pattern.compile(format);
    if (!pattern.matcher(str).matches()) {
      throw new Exception(ERROR_FORMAT);
    }

  }

  /**
   * 校验身份证号格式，支持旧身份证和二代身份证
   * @param cardNum
   * @return
   */
  public static boolean isCardNumber(String cardNum) {
    // 18位身份证号码正则
    String IDCard18_REGEX = "^[1-9](\\d{5})(19|20)(\\d{2})((0[1-9])|10|11|12)(([0-2][1-9])|10|20|30|31)(\\d{3})(\\d|X|x)$";
    // 15位身份证号码正则
    String IDCard15_REGEX = "^[1-9](\\d{5})(\\d{2})((0[1-9])|10|11|12)(([0-2][1-9])|10|20|30|31)(\\d{3})$";
    // 平年日期正则
    String OrdinaryYear_REGEX = "(((0[13578])|10|12)(([0-2][1-9])|10|20|30|31)|(((0[469])|11)(([0-2][1-9])|10|20|30))|(02(([0-2][1-8])|09|19|10|20)))";
    // 闰年日期正则
    String LeapYear_REGEX = "(((0[13578])|10|12)(([0-2][1-9])|10|20|30|31)|(((0[469])|11)(([0-2][1-9])|10|20|30))|(02(([0-2][1-9])|10|20)))";
    // 1-17位相乘因子数组
    int[] FACTOR = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};
    // 18位随机码数组
    char[] RANDOM = "10X98765432".toCharArray();

    boolean flag1 = false;
    boolean flag2 = false;
    boolean flag3 = true;

    // 判断第18位校验值
    if (cardNum.length() == 18) {
      flag1 = regexValidate(IDCard18_REGEX, cardNum);

      // 判断是不是闰年，并匹配日期是否规范
      int year = Integer.parseInt(cardNum.substring(6, 10));
      if (year % 4 == 0) {
        flag2 = regexValidate(LeapYear_REGEX, cardNum.substring(10, 14));
      } else {
        flag2 = regexValidate(OrdinaryYear_REGEX, cardNum.substring(10, 14));
      }

      char[] charArray = cardNum.toCharArray();
      char idCardLast = charArray[17];
      // 计算1-17位与相应因子乘积之和
      int total = 0;
      for (int i = 0; i < 17; i++) {
        total += Character.getNumericValue(charArray[i]) * FACTOR[i];
      }
      // 判断随机码是否相等
      char ch = RANDOM[total % 11];

      if (!String.valueOf(ch).toUpperCase().equals(String.valueOf(idCardLast).toUpperCase())) {
        flag3 = false;
      }
    } else if (cardNum.length() == 15) {
      flag1 = regexValidate(IDCard15_REGEX, cardNum);
      flag2 = regexValidate(OrdinaryYear_REGEX, cardNum.substring(8, 12));
    }
    return flag1 && flag2 && flag3;
  }

  private static boolean regexValidate(String regex, String value) {
    Pattern pattern = Pattern.compile(regex);
    Matcher matcher = pattern.matcher(value);
    return matcher.matches();
  }

  /**
   * 手机号码格式校验
   *
   * @param phoneNumber
   * @return
   */
  public static boolean isCellPhoneNumber(String phoneNumber) {
    boolean result = false;
    if (phoneNumber.length() == 11) {
      String regex = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$";
      Pattern p = Pattern.compile(regex);
      Matcher m = p.matcher(phoneNumber);
      result = m.matches();
    }
    return result;
  }

  /**
   * 固话号码校验
   *
   * @param phone
   * @return
   */
  public static boolean isPhoneNumber(String phone) {

    Matcher m;
    boolean result = false;
    String model;
    if (phone.length() > 9) {
      model="^[0][1-9]{2,3}-[0-9]{5,10}$";
      //带区号验证
    } else {
      model="^[1-9]{1}[0-9]{5,8}$";
      //没有区号的验证;
    }
    Pattern p = Pattern.compile(model);
    m = p.matcher(phone);
    result = m.matches();
    return result;
  }

  /**
   * 银行卡格式校验
   *
   * @param bankNumber
   * @return
   */
  public static boolean isBankNumber(String bankNumber) {

    if(bankNumber.length() < 15 || bankNumber.length() > 19) {
      return false;
    }
    char bit = getBankCardCheckCode(bankNumber.substring(0, bankNumber.length() - 1));
    if(bit == 'N'){
      return false;
    }
    return bankNumber.charAt(bankNumber.length() - 1) == bit;
  }

  /**
   * 从不含校验位的银行卡卡号采用 Luhm 校验算法获得校验位
   * @param nonCheckCodeBankCard
   * @return
   */
  private static char getBankCardCheckCode(String nonCheckCodeBankCard){
    if(nonCheckCodeBankCard == null || nonCheckCodeBankCard.trim().length() == 0
        || !nonCheckCodeBankCard.matches("\\d+")) {
      //如果传的不是数据返回N
      return 'N';
    }
    char[] chs = nonCheckCodeBankCard.trim().toCharArray();
    int luhmSum = 0;
    for(int i = chs.length - 1, j = 0; i >= 0; i--, j++) {
      int k = chs[i] - '0';
      if(j % 2 == 0) {
        k *= 2;
        k = k / 10 + k % 10;
      }
      luhmSum += k;
    }
    return (luhmSum % 10 == 0) ? '0' : (char)((10 - luhmSum % 10) + '0');
  }


  /**
   * 营业执照 统一社会信用代码（18位）校验
   * @param license
   * @return
   */
  public static boolean isLicense18(String license) {
    if(StringUtils.isBlank(license)) {
      return false;
    }
    if(license.length() != 18) {
      return false;
    }

    String regex = "^([159Y]{1})([1239]{1})([0-9ABCDEFGHJKLMNPQRTUWXY]{6})([0-9ABCDEFGHJKLMNPQRTUWXY]{9})([0-90-9ABCDEFGHJKLMNPQRTUWXY])$";
    if (!license.matches(regex)) {
      return false;
    }
    String str = "0123456789ABCDEFGHJKLMNPQRTUWXY";
    int[] ws = { 1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28 };
    String[] codes = new String[2];
    codes[0] = license.substring(0, license.length() - 1);
    codes[1] = license.substring(license.length() - 1, license.length());
    int sum = 0;
    for (int i = 0; i < 17; i++) {
      sum += str.indexOf(codes[0].charAt(i)) * ws[i];
    }
    int c18 = sum % 31;
    if (c18 == 0) {
      c18 = 31;
    }
    return codes[1].equals(str.charAt(31 - c18) + "");
  }


  /**
   * 营业执照 统一社会信用代码（15位）
   * @param license
   * @return
   */
  public static boolean isLicense15(String license) {
    if(StringUtils.isEmpty(license)) {
      return false;
    }
    if(license.length() != 15) {
      return false;
    }
    // 获取营业执照注册号前14位数字用来计算校验码
    String businesslicensePrex14 = license.substring(0,14);
    // 获取营业执照号的校验码
    String businesslicense15 = license.substring(14, license.length());
    char[] chars = businesslicensePrex14.toCharArray();
    int[] ints = new int[chars.length];
    for(int i=0; i<chars.length;i++) {
      ints[i] = Integer.parseInt(String.valueOf(chars[i]));
    }
    if(businesslicense15.equals(getCheckCode(ints)+"")) {
      // 比较 填写的营业执照注册号的校验码和计算的校验码是否一致
      return true;
    }
    return false;
  }

  /**
   * 获取 营业执照注册号的校验码
   * @param ints
   * @return
   */
  private static int getCheckCode(int[] ints) {
    if(null != ints && ints.length > 1) {
      int ti = 0;
      int si = 0;// pi|11+ti
      int cj = 0;// （si||10==0？10：si||10）*2
      int pj = 10;// pj=cj|11==0?10:cj|11
      for (int i=0;i<ints.length;i++) {
        ti = ints[i];
        pj = (cj % 11) == 0 ? 10 : (cj % 11);
        si = pj + ti;
        cj = (0 == si % 10 ? 10 : si % 10) * 2;
        if (i == ints.length-1) {
          pj = (cj % 11) == 0 ? 10 : (cj % 11);
          return pj == 1 ? 1 : 11 - pj;
        }
      }
    }// end if
    return -1;
  }

  /**
   * 判断年份是否有效
   * @param num
   * @return
   */
  public static boolean isYear(int num){
    return num<3000&&num>2000;
  }
}
